package com.ai.sml.interceptor;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
import org.springframework.web.bind.annotation.RequestMethod;

import com.ai.common.xml.bean.Action;
import com.ai.common.xml.bean.Input;
import com.ai.common.xml.bean.Parameter;
import com.ai.common.xml.util.ControlConstants;
import com.ai.common.xml.util.ControlRequestUtil;
import com.ai.frame.bean.InputObject;
import com.ai.frame.logger.Logger;
import com.ai.frame.logger.LoggerFactory;
import com.ai.frame.util.ConvertUtil;
import com.ai.sml.util.MyOwnRuntimeException;
import com.ai.sml.util.PropertiesUtil;
import com.ai.sml.util.StringUtil;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/**
 * 
 * 
 */
public class AuthorityInterceptor extends AbstractInterceptor {
	private static final long serialVersionUID = 8259007565097878289L;
	private static final Logger logger = LoggerFactory
			.getUtilLog(AuthorityInterceptor.class);

	public String intercept(ActionInvocation invocation) throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		String method = request.getMethod();
		String uri = request.getRequestURI();
		// 检查提交方式
		String type = request.getHeader("Content-Type");
		HttpServletResponse response = ServletActionContext.getResponse();
//		if (!uri.contains("!upload") && StringUtil.isNotEmpty(type) && type.contains("multipart/form-data")) {
//			response.setContentType("text/html");
//			response.getWriter().write("{\"returnCode\":\"-9999\",\"returnMessage\":\"无效的操作\"}");
//			return null;
//		}
//		if (!RequestMethod.POST.toString().equals(method)) {
//			response.setContentType("text/html");
//			response.getWriter().write("{\"returnCode\":\"-9999\",\"returnMessage\":\"无效的操作\"}");
//			return null;
//		}
		
		try {
			// 创建InputObject对象
	        createInputObject();
		} catch (Exception e) {
			logger.error("intercept", "intercept Exception", e);
			response.setContentType("text/html");
			response.getWriter().write("{\"returnCode\":\"-9999\",\"returnMessage\":\""+e.getMessage()+"\"}");
			return null;
		}
		
		return invocation.invoke();
	}

	private void createInputObject() throws MyOwnRuntimeException {
		String method = "createInputObject";
		HttpServletRequest request = ServletActionContext.getRequest();
		String path = request.getRequestURI();

		// 处理请求的URI
		if (path.endsWith(".action")) {
			path = path.substring(0, path.indexOf(".action"));
		}

		if (path.startsWith(request.getContextPath())) {
			path = path.substring(request.getContextPath().length(),
					path.length());
		}
		
		// 根据请求的路径取得配置的Action
		Action action;
		try {
			action = ControlRequestUtil.getActionByPath(path);
		} catch (Exception e1) {
			throw new MyOwnRuntimeException(e1);
		}

		// 获取特定的请求参数UID
		String uid = request.getParameter(ControlConstants.UID);
		if (StringUtil.isEmpty(uid)) {
			uid = null;
		}

		
		// 根据请求组装InputObject对象
		InputObject inputObject = new InputObject();
		try {
			String ip = InetAddress.getLocalHost().getHostAddress(); // 获取服务器IP地址
			inputObject.setServerIp(ip);
		} catch (Exception e) {
			logger.error(method, "Exception Occured When Try To Get IP Address !", e);
		}

		if (action != null) {
			Input input;
			try {
				input = ControlRequestUtil.getInputByUID(uid, action);
			} catch (Exception e) {
				throw new MyOwnRuntimeException(e);
			}
			processRequestParamters(request, inputObject, input);

			if (input != null) {
				if (StringUtil.isNotEmpty(input.getCode())) {
					inputObject.getParams().put("busiCode", input.getCode());
				}
                if (StringUtil.isNotEmpty(input.getBusiCode())) {
                    inputObject.setBusiCode(input.getBusiCode());
                }
				if (StringUtil.isNotEmpty(input.getService())) {
					inputObject.setService(input.getService());
				} 
				if (StringUtil.isNotEmpty(input.getMethod())) {
					inputObject.setMethod(input.getMethod());
				} 
			}
			ServletActionContext.getContext().put(ControlConstants.OUTPUT, ControlRequestUtil.getOutputByUID(uid, action));
		}
		ServletActionContext.getContext().put(ControlConstants.INPUTOBJECT, inputObject);
	}

	/**
	 * 处理参数
	 */
	private void processRequestParamters(
			HttpServletRequest request, InputObject inputObject, Input input) throws MyOwnRuntimeException {
		List<Parameter> parameters = this.getParameters(request, input);
		StringBuilder cacheKey = new StringBuilder();
		for (Parameter p : parameters) {
			Object object;
			String key = p.getKey();
			String toKey = p.getToKey();
			String scope = p.getScope();
            String defaultValue = p.getValue();
			if (StringUtil.isEmpty(defaultValue)) {
				defaultValue = "";
			}
			if (StringUtil.isEmpty(key)) {
				continue;
			}
			try {
				String[] values = request.getParameterValues(key);
				if (values == null || values.length == 1) {
					if (scope != null && ControlConstants.PARAM_SCOPE.SESSION.equals(scope)) {// 从Session读取参数
						String[] keys = key.split("[.]");
						object = request.getSession().getAttribute(keys[0]);
						for (int i = 1; i < keys.length; i++) {
							if (object == null) {
								break;
							}
							Method method = object.getClass().getMethod(ConvertUtil.getMethodByField(keys[i]));
							object = method.invoke(object);
						}
					} else if (scope != null
							&& ControlConstants.PARAM_SCOPE.CONSTANTS.equals(scope)) {// 从常量类中读�?
						Field field = Class.forName("com.zyzx.mall.util.Constants").getDeclaredField(key);
						object = field.get(field.getName());
					} else if (scope != null && ControlConstants.PARAM_SCOPE.PROPERTIES.equals(scope)) {// 从配置文件中读取
						object = PropertiesUtil.getString(key);
					} else if (scope != null && ControlConstants.PARAM_SCOPE.FILE.equals(scope)) {// 上传文件
                    	if (ServletFileUpload.isMultipartContent(request)) {
                        	MultiPartRequestWrapper multipartRequest = (MultiPartRequestWrapper)request;
                        	Map<?, ?> pMap = multipartRequest.getParameterMap();
							File[] files = multipartRequest.getFiles("file");
                        	if(files.length == 1) {
                                inputObject.addParams(key, toKey, ConvertUtil.file2String(files[0]));
                                inputObject.addParams(key + ControlConstants.FILE.FILENAME,
                                        toKey == null ? null : toKey + ControlConstants.FILE.FILENAME, ((String[])pMap.get("name"))[0]);
							}
							BigDecimal filesize = new BigDecimal(files[0].length());
							BigDecimal megabyte = new BigDecimal(1024 * 1024);
							float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue();
							String maxSize = inputObject.getParams().get("maxFileSize");
							if (maxSize != null && returnValue > Float.parseFloat(maxSize)) {
								throw new MyOwnRuntimeException("上传文件大小超过限制（" + maxSize + "M）");
							}
						} else {
							Map<String, Object> fileMap = ServletActionContext.getContext().getParameters();
							File[] files = (File[]) fileMap.get(key);
							if (files == null || files.length == 0) {
								continue;
							}
							
							String[] contentTypes = (String[]) fileMap.get(key + ControlConstants.FILE.CONTENTTYPE);
							String[] fileNames = (String[]) fileMap.get(key + ControlConstants.FILE.FILENAME);
							if (files.length == 1) {// 单个文件
								inputObject.addParams(key, toKey, ConvertUtil.file2String(files[0]));
								inputObject.addParams(key + ControlConstants.FILE.CONTENTTYPE, 
										toKey == null ? null : toKey + ControlConstants.FILE.CONTENTTYPE, contentTypes[0]);
								inputObject.addParams(key + ControlConstants.FILE.FILENAME, 
										toKey == null ? null : toKey + ControlConstants.FILE.FILENAME, fileNames[0]);
							} else {// 多个文件
								for (int i = 0; i < files.length; i++) {
									object = ConvertUtil.file2String(files[i]);
									inputObject.addBeans(key, toKey, i, String.valueOf(object));
									inputObject.addBeans(key + ControlConstants.FILE.CONTENTTYPE,
											toKey == null ? null : toKey + ControlConstants.FILE.CONTENTTYPE,
											i, contentTypes[i]);
									inputObject.addBeans(key + ControlConstants.FILE.FILENAME,
											toKey == null ? null : toKey + ControlConstants.FILE.FILENAME,
											i, fileNames[i]);
								}
							}
						}
						continue;
					} else {// 从request获取数据
						object = request.getParameter(key);
					}
					String value = object == null ? defaultValue : String.valueOf(object);
					value = StringUtils.trimToEmpty(value);
					inputObject.addParams(key, toKey, String.valueOf(value));//单行数据封装到Map<String,String> param
					cacheKey.append(key).append(String.valueOf(value));
				} else {// 多行数据提交
					for (int i = 0; i < values.length; i++) {
						inputObject.addBeans(key, toKey, i, values[i]);
					}
				}
				if (input.isCache()){
					inputObject.addParams(ControlConstants.CACHE_KEY, null, cacheKey.toString());
				}
			} catch (Exception e) {
				logger.error("processRequestParamters", "", e);
                throw new MyOwnRuntimeException("系统发生异常,请稍候再试!");
			}
		}
	}
	
	private List<Parameter> getParameters(HttpServletRequest request, Input input) {
		List<Parameter> params = new ArrayList<Parameter>();
		if (ControlConstants.INPUT_SCOPE.REQUEST.equals(input.getScope())) {// 从request中取key
			Enumeration<?> enumeration = request.getParameterNames();
			while (enumeration.hasMoreElements()) {
				String key = (String) enumeration.nextElement();
//				if (!ControlConstants.UID.equals(key))
				params.add(new Parameter(key, input.getToKeyByKey(key)));
			}
			for (Parameter param : input.getParameters()) {
				if (param.getScope() != null && !ControlConstants.PARAM_SCOPE.REQUEST.equals(param.getScope())){
					params.add(param);
				}
			}
		} else if (input.getScope() == null || ControlConstants.INPUT_SCOPE.CONTROL.equals(input.getScope())) {
			params.add(new Parameter(ControlConstants.UID, null));
			params.addAll(input.getParameters());
		}
		return params;
	}
}